package com.arithmeticEveryDay.divideAndConquer;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.StringTokenizer;

/*

在一个2^kx2^k (k>=1) 个方格组成的棋盘中，恰有一个方格与其他方格不同，称该方格为一将殊方格，且称该棋盘为一特珠棋盘。
在棋盘覆盖问翻中，要用图示的4种不同形志的L型骨牌盖特殊棋盘上的所有方格特殊方格除外)且任何2个L型骨牌不得重叠覆盖。

 */
public class CheckerboardCovering {

    static InOut1 io = new InOut1();
    int n, i;
    int[][] checkboard;

    public CheckerboardCovering() {
        int n = (int) Math.pow(2, io.nextInt());
        checkboard = new int[n][n];
        // i = 1;
        divide(0, 0, n, 0, 0);
    }

    private void divide(int startRow, int startColumn, int length, int specialRow, int specialColumn) {
        io.out.println(startRow + ", " + startColumn + ", " + length + ", " + specialRow + ", " + specialColumn);
        for (int x = 0; x < checkboard.length; x++) {
            for (int y = 0; y < checkboard.length; y++) {
                io.out.print(checkboard[x][y] + "\t");
            }
            io.out.println();
            io.out.println();
        }
        io.out.println();
        /*
        if (length == 1) {
            return;
        }
        i++;
        int mid = length/2;
        int iRecord = i;
        if (specialRow < startRow + mid && specialColumn < startColumn + mid) {
            divide(startRow, startColumn, mid, specialRow, specialColumn);
        } else {
            checkboard[startRow+mid-1][startColumn+mid-1] = iRecord;
            divide(startRow, startColumn, mid, startRow+mid-1, startColumn+mid-1);
        }
        
        if (specialRow < startRow + mid && specialColumn >= startColumn + mid) {
            divide(startRow, startColumn+mid, mid, specialRow, specialColumn);
        } else {
            checkboard[startRow+mid-1][startColumn+mid] = iRecord;
            divide(startRow, startColumn+mid, mid, startRow+mid-1, startColumn+mid);
        }
        
        if (specialRow >= startRow + mid && specialColumn < startColumn + mid) {
            divide(startRow+mid, startColumn, mid, specialRow, specialColumn);
        } else {
            checkboard[startRow+mid][startColumn+mid-1] = iRecord;
            divide(startRow+mid, startColumn, mid, startRow+mid, startColumn+mid-1);
        }
        
        if (specialRow >= startRow + mid && specialColumn >= startColumn + mid) {
            divide(startRow+mid, startColumn+mid, mid, specialRow, specialColumn);
        } else {
            checkboard[startRow+mid][startColumn+mid] = iRecord;
            divide(startRow+mid, startColumn+mid, mid, startRow+mid, startColumn+mid);
        }
        
        io.out.println(startRow + ", " + startColumn + ", " + length + ", " + specialRow + ", " + specialColumn);
        for (int x = 0; x < checkboard.length; x++) {
            for (int y = 0; y < checkboard.length; y++) {
                io.out.print(checkboard[x][y] + "\t");
            }
            io.out.println();
            io.out.println();
        }
        io.out.println();
        */
        int mid = length / 2;
        if (length < 2) {
            return;
        } else if (length == 2) {
            if (specialRow < startRow + mid && specialColumn < startColumn + mid) {
                checkboard[startRow][startColumn+1] = i;
                checkboard[startRow+1][startColumn] = i;
                checkboard[startRow+1][startColumn+1] = i;
            } else if (specialRow < startRow + mid && specialColumn >= startColumn + mid) {
                checkboard[startRow][startColumn] = i;
                checkboard[startRow+1][startColumn] = i;
                checkboard[startRow+1][startColumn+1] = i;
            } else if (specialRow >= startRow + mid && specialColumn < startColumn + mid) {
                checkboard[startRow][startColumn] = i;
                checkboard[startRow][startColumn+1] = i;
                checkboard[startRow+1][startColumn+1] = i;
            } else if (specialRow >= startRow + mid && specialColumn >= startColumn + mid) {
                checkboard[startRow][startColumn] = i;
                checkboard[startRow][startColumn+1] = i;
                checkboard[startRow+1][startColumn] = i;
            }
            i++;
        } else {
            if (specialRow < startRow + mid && specialColumn < startColumn + mid) {
                checkboard[startRow + mid - 1][startColumn + mid] = i;
                checkboard[startRow + mid][startColumn + mid - 1] = i;
                checkboard[startRow + mid][startColumn + mid] = i;
                i++;
                io.out.println();
                divide(startRow, startColumn, mid, specialRow, specialColumn);
                divide(startRow, startColumn + mid, mid, startRow + mid - 1, startColumn + mid);
                divide(startRow + mid, startColumn, mid, startRow + mid, startColumn + mid - 1);
                divide(startRow + mid, startColumn + mid, mid, startRow + mid, startColumn + mid);
            } else if (specialRow < startRow + mid && specialColumn >= startColumn + mid) {
                checkboard[startRow + mid - 1][startColumn + mid - 1] = i;
                checkboard[startRow + mid][startColumn + mid - 1] = i;
                checkboard[startRow + mid][startColumn + mid] = i;
                i++;
                divide(startRow, startColumn, mid, startRow + mid - 1, startColumn + mid - 1);
                divide(startRow, startColumn + mid, mid, specialRow, specialColumn);
                divide(startRow + mid, startColumn, mid, startRow + mid, startColumn + mid - 1);
                divide(startRow + mid, startColumn + mid, mid, startRow + mid, startColumn + mid);
            } else if (specialRow >= startRow + mid && specialColumn < startColumn + mid) {
                checkboard[startRow + mid - 1][startColumn + mid - 1] = i;
                checkboard[startRow + mid - 1][startColumn + mid] = i;
                checkboard[startRow + mid][startColumn + mid] = i;
                i++;
                divide(startRow, startColumn, mid, startRow + mid - 1, startColumn + mid - 1);
                divide(startRow, startColumn + mid, mid, startRow + mid - 1, startColumn + mid);
                divide(startRow + mid, startColumn, mid, specialRow, specialColumn);
                divide(startRow + mid, startColumn + mid, mid, startRow + mid, startColumn + mid);
            } else if (specialRow >= startRow + mid && specialColumn >= startColumn + mid) {
                checkboard[startRow + mid - 1][startColumn + mid - 1] = i;
                checkboard[startRow + mid - 1][startColumn + mid] = i;
                checkboard[startRow + mid][startColumn + mid - 1] = i;
                i++;
                divide(startRow, startColumn, mid, startRow + mid - 1, startColumn + mid - 1);
                divide(startRow, startColumn + mid, mid, startRow + mid - 1, startColumn + mid);
                divide(startRow + mid, startColumn, mid, startRow + mid, startColumn + mid - 1);
                divide(startRow + mid, startColumn + mid, mid, specialRow, specialColumn);
            }
        }
        
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        CheckerboardCovering c = new CheckerboardCovering();
        for (int x = 0; x < c.checkboard.length; x++) {
            for (int y = 0; y < c.checkboard.length; y++) {
                io.out.print(c.checkboard[x][y] + "\t");
            }
            io.out.println();
            io.out.println();
        }
        io.out.println();
        io.out.flush();
    }

}

class InOut1 {
    BufferedReader br;
    StringTokenizer tok;
    PrintWriter out;

    InOut1() {
        br = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintWriter(new OutputStreamWriter(System.out));
    }

    public boolean hasNext() {
        while (tok == null || !tok.hasMoreElements()) {
            try {
                tok = new StringTokenizer(br.readLine());
            } catch (IOException e) {
                // TODO Auto-generated catch block
                return false;
            }
        }
        return true;
    }

    public String next() {
        if (hasNext()) {
            return tok.nextToken();
        }
        return null;
    }

    public int nextInt() {
        return Integer.parseInt(next());
    }
}